#include "QDRTestMaster.h"


QWidget *QDRTestMaster::controlPanel=0;
QWidget *QDRTestMaster::agentPanel=0;
QDialog *QDRTestMaster::selectWidget=0;
QDialog *QDRTestMaster::indicateWidget=0;
QDRTestMaster *QDRTestMaster::rootTestMaster=0;

//------------------------------------------------------------
//[static]
QDRTestMaster *QDRTestMaster::get_rootTestMaster()
{
       //если нет никого - создадим его.
       if (QDRTestMaster::rootTestMaster==0)
         {
            QDRTestMaster::rootTestMaster = new QDRTestMaster();
         };
        return QDRTestMaster::rootTestMaster;
}

/*============================================================
Далее у нас 2 части в данном файле.
Те что касаются 2-хнаших классов.

*/
QDRTestMaster::QDRTestMaster(QObject *parent) :
    QObject()
{

    //первый же мастер и будет "корневым"
    if (QDRTestMaster::rootTestMaster==0)
    {
       QDRTestMaster::rootTestMaster = this;
    };

    //нам нужен свой поток, для того, что бы нормально обрабатываться когда появляются модальные окна с приостановкой работы приложения.
    QThread *newThread=new QThread(parent);


    ttimer=new t_timerSender();
    ttimer->moveToThread(newThread);//таймер предоствращения от замираний...
    ttimer->myTimer.setInterval(300);
    ttimer->myTimer.start();
    connect(ttimer,SIGNAL(timeout()),this,SLOT(playNextActionTimerEvent()));

    newThread->start();

    timer = new QTimer();
    //timer->moveToThread(newThread);
    bool rez= connect(timer,SIGNAL(timeout()),this,SLOT(playNextActionTimerEvent()));

    this->moveToThread(qApp->thread());
    eventFilter = new QDRTestMaster_eventFilter(this);
    eventFilter->moveToThread(qApp->thread());

    compressMouseMoves=__filterMouseMoveEvents;

//    //не очень хорошо, но пусть пока будет так
//    QTextCodec *defaultCodec = QTextCodec::codecForName("UTF-8");
//    QTextCodec::setCodecForTr(defaultCodec);
//    QTextCodec::setCodecForCStrings(defaultCodec);
    outfile=0;
    infile=0;

    if (QDRTestMaster::controlPanel==0)
        {
          QDRTestMaster::controlPanel=get_controlPanel();

          QObject::connect (qApp,SIGNAL(aboutToQuit()),QDRTestMaster::controlPanel,SLOT(deleteLater()));
        };

    //панель агента - висит в правом верхнем углу маленькая для быстрого доступа к функциям
    if (QDRTestMaster::agentPanel==0)
        {
            QDRTestMaster::agentPanel=get_agentPanel();

        }

    //виджет выбора. Полупрозрачная фигня которая принимает размеры виджета над которым мы сейчас находимся.
    // работает только в режиме выбора виджета.
    if (QDRTestMaster::selectWidget==0)
        {
            QDRTestMaster::selectWidget = new QDialog();//QWidget();
            //QDRTestMaster::selectWidget->moveToThread(newThread);

            QLabel *label=new QLabel( QDRTestMaster::selectWidget);
            label->move(3,0);
            label->setText("");
            label->resize(100,15);
            connect(this,SIGNAL(setSelectWidgetText(QString)),label, SLOT(setText(QString)));

            //QDRTestMaster::selectWidget->grabMouse();

            QObject::connect (QDRTestMaster::controlPanel,SIGNAL(destroyed()),QDRTestMaster::selectWidget,SLOT(deleteLater()));
            QDRTestMaster::selectWidget->setWindowOpacity(0.5);
            QDRTestMaster::selectWidget->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint|Qt::ToolTip);


            QPalette pal = QPalette();
            pal.setBrush(QPalette::Window, QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
            QDRTestMaster::selectWidget->setPalette(pal);
        };

    //индикатор того, что виджет под курсором распознан.
    //если он зеленый с галочкой - значит наше действие будет успешно распознано.
    if (QDRTestMaster::indicateWidget==0)
        {
            QDRTestMaster::indicateWidget = new QDialog();//QWidget();
            //QDRTestMaster::selectWidget->moveToThread(newThread);

            QObject::connect (QDRTestMaster::controlPanel,SIGNAL(destroyed()),QDRTestMaster::indicateWidget,SLOT(deleteLater()));
            QDRTestMaster::indicateWidget->setWindowOpacity(0.5);
            QDRTestMaster::indicateWidget->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint|Qt::ToolTip);


            QPalette pal = QPalette();
            pal.setBrush(QPalette::Window, QBrush(QColor(0,0,0,0)) );//QBrush(QPixmap( ":/images/bg1.png"))
            QDRTestMaster::indicateWidget->setPalette(pal);
        };



    controlPanelWidgetSelectingMode=false;
    controlPanelWidgetSelectingSubMode=0;


            logfile=new QFile("total_event_log.txt");
            bool cRez=logfile->open(QIODevice::Append | QIODevice::Text);//откроем на дозапись
            logfile->resize(0);
            if (!cRez) {/*error*/qDebug() << "ERROR: QDRTestMaster::startRecordingActionsToFile()[00033] can`t open file for record." << "total_event_log.txt";};

            logStream = new QTextStream(logfile);
            logStream->setCodec(QTextCodec::codecForName("UTF-8"));

    QDRTestMaster::controlPanel->setProperty("inKeyPressOperation",false);

}

//---------------------------------
//умное разделение -т.е. с учетом символа экранирования "\"
// но и одновременно с раскрытием экранироваия
//ВЫНЕСТИ В BBot?!
QStringList QDRTestMaster::cleverSplit(QString source, QString splitChar)
{
    QStringList rezList;
    QStringMap rezMap;
    int q;
    QString srcCopy=source, cString="", cChar="";
    bool slashed=false;
    for (q=0;q<srcCopy.length();q++)
        {
            cChar=srcCopy.at(q);
            if ((cChar=="\\") and (slashed==false))
                {
                    slashed=true;
                    continue;
                };
            if (
                        (cChar!=splitChar)
                        or
                        ((cChar==splitChar) and (slashed==true))
               )
                {
                    cString=cString+cChar;
                }
            else
                {
                    rezList.append(cString);
                    cString="";
                }
            slashed=false;
        };
    rezList.append(cString);
    return rezList;
}

//=====================================================================================
//разделяем строку именованных параметров на имя=значение
// с учетом разделителей и символов экранирования.
// имя не должно содержать ни "символов экранирования", ни "разделителя", ни "равно"
QStringMap QDRTestMaster::cleverSplitToMap(QString source, QString splitChar, bool trimKeys)
{
    QStringMap rezMap;
    QStringList rezList=cleverSplit(source, splitChar);
    QString cStr,cKey,cValue;
    int q,cEqPos;
    for (q=0;q<rezList.size();q++)
        {
            cStr=rezList.at(q);
            cEqPos=cStr.indexOf("=");
            if (cEqPos>0)
                {
                    cKey=cStr.left(cEqPos);
                    if (trimKeys) cKey=cKey.trimmed();
                    cValue=cStr.mid(cEqPos+1);
                    rezMap.insert(cKey,cValue);
                }
              else
                {
                    if (trimKeys) cStr=cStr.trimmed();
                    rezMap.insert(cStr,"");
                };
        };
    return rezMap;
}

//--------------------------------------------------------------------------
//функция для удобства работы с динамически формируемыми виджетами...
void QDRTestMaster::setTextOnWidget(QWidget *widg, QString labelName, QString text)
{
    QLineEdit *tmpLineEdit;
    QLabel *tmpLabel;
    QLineEdit *tmpLEdit;
    QTextEdit *tmpTextEdit;
    QTextBrowser *tmpTextBrowser;
    QObject *someObject;
    QString className;

    someObject = qFindChild<QObject *> (widg, labelName ); //для MSVC
    if (someObject==NULL)
      {
        qDebug() << "t_infoObjectWidget::get_valuOnWidget()[0317]: WARNING: cant find widget for field [" << labelName << "]";
        return;// retValue;// .isNull()==true!
      };
    className = someObject->metaObject()->className();//получаем имя класса в виде строки.

    // а теперь в зависимости от типа класса по ссылке - работаем с ним по разному
    // все ради того, что бы в последствии можно было разместить на форме и счетчики,
    // и кучу других виджетов ...
    if (className=="QLabel")
      {
        tmpLabel = (QLabel *)someObject;
        tmpLabel->setText(text);
      }
     else if (className=="QLineEdit")
      {
        tmpLEdit = (QLineEdit *)someObject;
        tmpLEdit->setText(text);
      }
     else if (className=="QTextBrowser")
            {
              tmpTextBrowser = (QTextBrowser *)someObject;
              tmpTextBrowser->setHtml(text);
            };

}

//--------------------------------------------------------------------------
//функция для удобства работы с динамически формируемыми виджетами...
QString QDRTestMaster::getTextOnWidget(QWidget *widg,QString labelName)
{
    QString retVal=QString();

    QLineEdit *tmpLineEdit;
    QLabel *tmpLabel;
    QLineEdit *tmpLEdit;
    QTextEdit *tmpTextEdit;
    QTextBrowser *tmpTextBrowser;
    QComboBox *tmpComboBox;

    QObject *someObject;
    QString className;

    someObject = qFindChild<QObject *> (widg, labelName ); //для MSVC
    if (someObject==NULL)
      {
        qDebug() << "t_infoObjectWidget::get_valuOnWidget()[0317]: WARNING: cant find widget for field [" << labelName << "]";
        return retVal;// retValue;// .isNull()==true!
      };
    className = someObject->metaObject()->className();//получаем имя класса в виде строки.

    // а теперь в зависимости от типа класса по ссылке - работаем с ним по разному
    // все ради того, что бы в последствии можно было разместить на форме и счетчики,
    // и кучу других виджетов ...
    if (className=="QLabel")
      {
        tmpLabel = (QLabel *)someObject;
        retVal=tmpLabel->text();
      }
     else if (className=="QLineEdit")
      {
        tmpLEdit = (QLineEdit *)someObject;
        retVal=tmpLEdit->text();
      }
     else if (className=="QComboBox")
      {
        tmpComboBox = (QComboBox *)someObject;
        retVal=tmpComboBox->currentText();
      }
     else if (className=="QTextBrowser")
            {
              tmpTextBrowser = (QTextBrowser *)someObject;
              retVal=tmpTextBrowser->toHtml();
            };
     return retVal;
}
//---------------------------------
/* экранировать заданный символ во всех вхождениях в заданной строке

   [STATIC]
*/
QString QDRTestMaster::escapeCharacters(QString source, QString charToEscape)
{
    int q;
    QString srcCopy=source, cString="", cChar="";
    for (q=0;q<srcCopy.length();q++)
        {
            cChar=srcCopy.at(q);
            if (cChar==charToEscape)
                {
                    cString=cString+"\\";
                };
            cString=cString+cChar;
        };
    return cString;

}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
QString QDRTestMaster::lastError()
    {
        return lastErrorString;
    }
int QDRTestMaster::setLastError(QString _newErr)
    {
        lastErrorString=_newErr;
        return 0;
    }



//------------------------------------------------------------
void QDRTestMaster::installAppEventHandler()
    {
        QCoreApplication::instance()->installEventFilter(eventFilter); //устанавливаем фильтр событий
    }

//------------------------------------------------------------
//[static]
void QDRTestMaster::st_sendTestLog(QString logMessage)
    {
        QDRTestMaster::get_rootTestMaster()->sendTestLog(logMessage);
    }

//------------------------------------------------------------
//[static]
void QDRTestMaster::st_clearTestLog()
    {
        QDRTestMaster::get_rootTestMaster()->clearTestLog();
    }
//------------------------------------------------------------
int QDRTestMaster::startRecord(QString fileName)
    {
        if (outfile==0)
            {
                outfile=new QFile(fileName);
                bool cRez=outfile->open(QIODevice::Append | QIODevice::Text);//откроем на дозапись
                outfile->resize(0);
                if (!cRez)
                    {/*error*/
                        qDebug() << "ERROR: QDRTestMaster::startRecordingActionsToFile()[00033] can`t open file for record." << fileName;
                        outfile->close();
                        outfile=0;
                        return -100;
                    };

                outStream = new QTextStream(outfile);
                outStream->setCodec(QTextCodec::codecForName("UTF-8"));
                st_clearTestLog();

                QDRTestMaster::indicateWidget->resize(32,32);
                QDRTestMaster::indicateWidget->show();


                return 0;
            };
        return -1;
    }

//------------------------------------------------------------
void QDRTestMaster::stopRecord()
{
    if (outfile!=0)
        {
            outStream->flush();
            outfile->flush();
            qApp->processEvents();
            timer->stop();

            outStream->~QTextStream();
            outfile->close();
            outfile=0;
            selectWidget->hide();
        };
}


//------------------------------------------------------------------------
/*
полученное от виджета значение надо обработать перед тем как записать в сценарий.
Пока у нас одна строка текста - один action. и менять это пока лень.


*/
QString QDRTestMaster::escapeAndPrepareValueStringForRecording(QString src)
{
    QString textS=src;
    textS=QDRTestMaster::escapeCharacters(textS,"\\");
    textS=QDRTestMaster::escapeCharacters(textS," ");
    textS=QDRTestMaster::escapeCharacters(textS,"\"");
    textS=QDRTestMaster::escapeCharacters(textS,";");
    textS=QDRTestMaster::escapeCharacters(textS,"#");
    textS=QDRTestMaster::escapeCharacters(textS,"\\");
    textS=textS.replace("\n","{{ENTER}}");
    return textS;
}

QString QDRTestMaster::dePrepareValueStringFromRecording(QString src)
{
    QString textS=src;
//    textS=QDRTestMaster::escapeCharacters(textS," ");
//    textS=QDRTestMaster::escapeCharacters(textS,"\"");
//    textS=QDRTestMaster::escapeCharacters(textS,";");
//    textS=QDRTestMaster::escapeCharacters(textS,"#");
//    textS=QDRTestMaster::escapeCharacters(textS,"\\");
    textS=textS.replace("{{ENTER}}","\n");
    return textS;
}

//------------------------------------------------------------------------
//просто проверка того как это будет выглядеть если управлять мышьючерез QtTest
int QDRTestMaster::testAction()
{

    //startPlay("./userActionsRecord.posb.rec.2play.txt");
    get_controlPanel()->show();
};

//------------------------------------------------------------
//проигрывание будем следущим образом...
// 20 (пусть пока так) будет тикать таймер.
// по таймеру мы выбираем очередную порцию записей по нашим активностям
// и проигрываем это.
int QDRTestMaster::startPlay(QString fileName)
    {
        QPalette pal;
        if (infile==0)
            {


                infile=new QFile(fileName);
                bool cRez=infile->open(QIODevice::ReadOnly | QIODevice::Text);//откроем на чтение

                if (!cRez)
                    {/*error*/
                        setLastError(QString("ERROR: QDRTestMaster::startPlay()[00368] can`t open file for read. [%1]").arg(fileName));
                        qDebug() << lastError();//"ERROR: QDRTestMaster::startPlay()[00061] can`t open file for read." << fileName;
                        infile->close();
                        infile=0;
                        return -100;
                    };

                inStream = new QTextStream(infile);
                inStream->setCodec(QTextCodec::codecForName("UTF-8"));

                actionCounter=0;
                controlPanel->hide();

                timeoutMsecToNextAction=300;// первый раз - с задержкой...
                timer->setSingleShot(true);
                timer->setInterval(timeoutMsecToNextAction);
                timer->start();

                //playTimerId=qApp->startTimer(timeoutMsecToNextAction);
                //eventFilter->qApp_PlayTimerId=playTimerId;

                st_clearTestLog();
                emit playStarted(QDateTime::currentDateTime().toString(dateTimeStrFormat), "Starting to play scenario: "+fileName);


                 //QBrush(QColor("green")) );//QBrush(QPixmap( ":/images/bg1.png"))
                pal.setBrush(QPalette::Window, QBrush(QColor("blue")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                QDRTestMaster::selectWidget->resize(50,25);
                QDRTestMaster::selectWidget->setPalette(pal);
                selectWidget->show();



                return true;
            };
        return false;
    }

//------------------------------------------------------------------------
//играем не очень понятно... но попоробую объяснить.
/*
Мы получаем новое описание действия. По временной метке в нем записанной и последним выполненным
 - рассчитываем задержку до следующего дейтсвия...
и активируем таймер, который нас же вызовет.
После активации по таймеру - выполняем ранее полученное действие,
а потом - снова - читаем новое дейтсвие, витаем метку времени и вызываем таймер...

*/
//[SLOT]
void QDRTestMaster::playNextActionTimerEvent()
    {
        //qDebug()<< "t_timerSender::playNextActionTimerEvent()";
        //QString nextAction;
        if (infile!=0)
            {
               QDateTime nextDateTime_inFile;//записанное время (следующего) шага в файле

               QDateTime now = QDateTime::currentDateTime();
             //  int msecsFrom=lastDateTime_real.time().msecsTo(now.time());

             //  if (msecsFrom<0) msecsFrom=timeoutMsecToNextAction;
                                //милисекунды могут быть меньше нуля - если сегодня мы играем раньше, чем записывали вчера.
             //  if (msecsFrom<timeoutMsecToNextAction) //страхование от замерзания основного счетчика
             //          return; //значит попали сюда по страховому счетчику но до заданного таймаута

               do //прокрутим за раз несколько событий если они в один момент времени (одну миллисекунду)
               {
                    if (!nextActionToPlay.isEmpty())
                        {
                            playAction(nextActionToPlay);
                        };
                     //timer->stop();

                     if (infile!=0) nextActionToPlay=inStream->readLine(4000);//ограничим на всякий случай
                     if (nextActionToPlay.isNull())
                        {
                            stopPlay("Scenario finished | File Ended.");
                            return;
                        };

                     QString separator=";";
                     bool trimKeys=true;
                     QStringMap nextActionToPlayOptionMap=QDRTestMaster::cleverSplitToMap(nextActionToPlay,separator,trimKeys);

                     nextDateTime_inFile = QDateTime::fromString(nextActionToPlayOptionMap.value("time").trimmed(), dateTimeStrFormat );

                     //тут пытаемся получить разницу в милисекундах между двумя временными метками.
                     //int msecsTo=actionPlayTimePos.time().msecsTo(dateTime.time());
                     timeoutMsecToNextAction = lastDateTime_inFile.time().msecsTo(nextDateTime_inFile.time());


                     if (timeoutMsecToNextAction<0)
                         {
                             timeoutMsecToNextAction=10;
                         };

                     if (timeoutMsecToNextAction>500)
                         {
                             timeoutMsecToNextAction=500;
                         }
                     lastDateTime_inFile=nextDateTime_inFile;

//                     if (timeoutMsecToNextAction==0)
//                         qDebug();

                } while ((timeoutMsecToNextAction==0) and (!nextActionToPlay.isNull()));

                lastDateTime_real=now;
                timer->setSingleShot(true);
                timer->setInterval(timeoutMsecToNextAction);
                timer->start();


                 //qApp->killTimer(playTimerId); //недеюсь, это будет срабатывать даже при отображении модальных окон...
                 //playTimerId=startTimer(timeoutMsecToNextAction);
                 //eventFilter->qApp_PlayTimerId=playTimerId;

            };
    };

//------------------------------------------------------------------------
//[static]
QWidget *QDRTestMaster::waitForWidgetAppear(QString widgetName, int timeoutMs)
    {
        QWidget *targetWidget=get_widgetByNamePath(widgetName);
//        for (int i=0;(targetWidget==0) && (i<timeoutMs); i=i+300)
//            {
//                //QApplication::processEvents();
//                QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
//                //QTest::qSleep(50);
//                targetWidget=get_widgetByNamePath(widgetName);
//            };
        return targetWidget;
    }
//------------------------------------------------------------------------
//[static]
bool QDRTestMaster::waitForWidgetDisAppear(QString widgetName, int timeoutMs)
    {
        QWidget *targetWidget=get_widgetByNamePath(widgetName);
//        int i = 0;
//         while (targetWidget!=0 && i<timeoutMs)
//            {
//                //QApplication::processEvents();
//                QTest::qWait(300);
//                i=+300;
//                targetWidget=get_widgetByNamePath(widgetName);
//            };
        return (targetWidget==0);
    }
//------------------------------------------------------------------------
//проиграть записанную акцию
/*

*/
int QDRTestMaster::playAction(QString actionDescription)
    {
        QString separator=";";
        QString checkNotes;

        QPalette pal;
        QDateTime    time;
        QString      objectNamePath;
        QString      action;
        QString      actionOptions;
        bool rez;
        if (infile==0) return -10; // не открыт  файл (не запущен "режим проигрывания")

        bool trimKeys=true;
        //TODO: карту опций собственно можно бы и сохранять - мы-ж её уже разбирали
        //  -- см nextActionToPlayOptionMap

        QStringMap commap=QDRTestMaster::cleverSplitToMap(actionDescription,separator,trimKeys);
        //time = QDateTime::fromString(commap.value("time").trimmed(), dateTimeStrFormat );
        objectNamePath = commap.value("object").trimmed();
        action = commap.value("action").trimmed();
        actionOptions = commap.value("options").trimmed();

         action=action.trimmed();
         if (action=="MouseMove")
                {
                  QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions, QString(" "));
                  //QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                  QWidget *targetWidget=waitForWidgetAppear(objectNamePath,500);
                  if (targetWidget==0)
                    {
                      sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                      return -2;//виджет не найден
                    };

                  QPoint localPos=QPoint(optmap.value("x").toInt(),optmap.value("y").toInt());
                  QTest::mouseMove( targetWidget , localPos);

                  //индикация
                  pal.setBrush(QPalette::Window, QBrush(QColor("blue")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                  QDRTestMaster::selectWidget->setPalette(pal);
                  selectWidget->move(targetWidget->mapToGlobal(localPos));

                  ////окошко выделения тек. виджета тоже выделяем...
                  //QPoint globPo=targetWidget->mapToGlobal(localPos);
                  ////moveSelectionWidget(globPo.x(), globPo.y());
                }

           else if (action=="MouseButtonPress")
                {

                  QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                  //QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                  QWidget *targetWidget=waitForWidgetAppear(objectNamePath,500);
                  if (targetWidget==0)
                    {
                      checkNotes=QString("ERROR: WIDGET NOT FOUND!");
                      emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                      sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                      return -2;//виджет не найден
                    };
                  int modifers=optmap.value("modifiers").trimmed().toInt();
                  Qt::MouseButton mButton = QDRTestMaster::String2QtMouseButton(optmap.value("button").trimmed());

                  //пока просто повыводим что мы извлекли в отладочное окно.
                  QTest::mousePress( targetWidget, mButton, (Qt::KeyboardModifier)modifers, QPoint(optmap.value("x").toInt(), optmap.value("y").toInt()));

                  QPoint localPos=QPoint(optmap.value("x").toInt(),optmap.value("y").toInt());
                  //индикация
                  pal.setBrush(QPalette::Window, QBrush(QColor("yellow")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                  selectWidget->setPalette(pal);
                  selectWidget->move(targetWidget->mapToGlobal(localPos));
                }

           else if (action=="MouseButtonRelease")
                {

                  QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                  //QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                  QWidget *targetWidget=waitForWidgetAppear(objectNamePath,500);
                  if (targetWidget==0)
                    {
                      checkNotes=QString("ERROR: WIDGET NOT FOUND!");
                      emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                      sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                      return -2;//виджет не найден
                    };
                  int modifers=optmap.value("modifiers").trimmed().toInt();
                  Qt::MouseButton mButton = QDRTestMaster::String2QtMouseButton(optmap.value("button").trimmed());

                  QTest::mouseRelease( targetWidget, mButton, (Qt::KeyboardModifier)modifers, QPoint(optmap.value("x").toInt(), optmap.value("y").toInt()));

                  QPoint localPos=QPoint(optmap.value("x").toInt(),optmap.value("y").toInt());
                  //индикация
                  pal.setBrush(QPalette::Window, QBrush(QColor("blue")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                  QDRTestMaster::selectWidget->setPalette(pal);
                  selectWidget->move(targetWidget->mapToGlobal(localPos));
              }

           else if (action=="MouseButtonDblClick")
                {

                  QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                  //QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                  QWidget *targetWidget=waitForWidgetAppear(objectNamePath,500);
                  if (targetWidget==0)
                    {
                      checkNotes=QString("ERROR: WIDGET NOT FOUND!");
                      emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                      sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                      return -2;//виджет не найден
                    };
                  int modifers=optmap.value("modifiers").trimmed().toInt();
                  Qt::MouseButton mButton = QDRTestMaster::String2QtMouseButton(optmap.value("button").trimmed());


                  QPoint localPos=QPoint(optmap.value("x").toInt(),optmap.value("y").toInt());
                  //индикация
                  pal.setBrush(QPalette::Window, QBrush(QColor("yellow")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                   QDRTestMaster::selectWidget->setPalette(pal);
                   selectWidget->move(targetWidget->mapToGlobal(localPos));
                  pal.setBrush(QPalette::Window, QBrush(QColor("blue")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                   QDRTestMaster::selectWidget->setPalette(pal);
                   selectWidget->move(targetWidget->mapToGlobal(localPos));

                  QTest::mouseDClick( targetWidget, mButton, (Qt::KeyboardModifier)modifers, QPoint(optmap.value("x").toInt(), optmap.value("y").toInt()));
                }

           else if (action=="Move")
                {
                   QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                   //QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                   QWidget *targetWidget=waitForWidgetAppear(objectNamePath,500);
                   if (targetWidget==0)
                     {
                       checkNotes=QString("ERROR: WIDGET NOT FOUND!");
                       emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                       sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                       return -2;//виджет не найден
                     };
                   int moveX=optmap.value("movex").trimmed().toInt();
                   int moveY=optmap.value("movey").trimmed().toInt();

                   //QPoint localPos=QPoint(moveX,moveY);
                   //индикация
                   pal.setBrush(QPalette::Window, QBrush(QColor("green")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                   QDRTestMaster::selectWidget->setPalette(pal);
                   selectWidget->move(targetWidget->mapToGlobal(QPoint(0,0)));

                   targetWidget->move(targetWidget->pos().x()+moveX, targetWidget->pos().y()+moveY);

                }

           else if (action=="Resize")
                {
                   QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                   //QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                   QWidget *targetWidget=waitForWidgetAppear(objectNamePath,500);
                   if (targetWidget==0)
                     {
                       checkNotes=QString("ERROR: WIDGET NOT FOUND!");
                       emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                       sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                       return -2;//виджет не найден
                     };
                   int height=optmap.value("height").trimmed().toInt();
                   int width=optmap.value("width").trimmed().toInt();
                   int oldH=targetWidget->size().height();
                   int oldW=targetWidget->size().width();

                   targetWidget->resize(width, height);
                }
           else if (action=="TestValue")
                {
                   QString checkNotes;
                   //QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                   QWidget *targetWidget=waitForWidgetAppear(objectNamePath,500);

                   if (targetWidget==0)
                     {
                       //sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                       checkNotes=QString("ERROR: WIDGET NOT FOUND!");
                       emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                       sendTestLog(QString("<font color=red><b>ERROR: TEST FAILED</b></font> ::").append(actionDescription));
                       return -2;//виджет не найден
                     };
                   QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                   QString checkid=optmap.value("checkid").trimmed();
                   QString property=optmap.value("property").trimmed();
                   QString value=optmap.value("value").trimmed();
                           value=dePrepareValueStringFromRecording(value);


                   QString compareType=optmap.value("compareType").trimmed();
                   QString note=optmap.value("note").trimmed();

//                   QString valueOnVidget=targetWidget->property(property.toLocal8Bit().constData()).toString();
                   QString valueOnVidget=get_valueFromWidget_useOptions(targetWidget,actionOptions);

                   //compareType ==== equal

                   checkNotes=QString(" <br>property: %3 <br> <b>WAITED:</b>%4[%2]<b><br> FOUND:</b>[%1]").arg(valueOnVidget.trimmed()).arg(value.trimmed()).arg(property).arg(compareType);

                        if (compareType=="equal") {rez=(valueOnVidget.trimmed()==value.trimmed());}
                   else if (compareType=="starts_with") {rez=(valueOnVidget.trimmed().startsWith(value.trimmed()));}
                   else if (compareType=="ends_with") {rez=(valueOnVidget.trimmed().endsWith(value.trimmed()));}
                   else if (compareType=="contains") {rez=(valueOnVidget.trimmed().contains(value.trimmed()));}
                   else if (compareType=="not_equal") {rez=!(valueOnVidget.trimmed()==value.trimmed());}
                   else if (compareType=="not_starts_with") {rez=!(valueOnVidget.trimmed().startsWith(value.trimmed()));}
                   else if (compareType=="not_ends_with") {rez=!(valueOnVidget.trimmed().endsWith(value.trimmed()));}
                   else if (compareType=="not_contains") {rez=!(valueOnVidget.trimmed().contains(value.trimmed()));}
                   else if (compareType=="less_int") {rez=(valueOnVidget.trimmed().toInt()<value.trimmed().toInt());}
                   else if (compareType=="more_int") {rez=(valueOnVidget.trimmed().toInt()>value.trimmed().toInt());};


                   if (!rez)
                        {
                           checkNotes="ERR: check faled <br>"+checkNotes;
                           emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                           sendTestLog(QString("<font color=red><b>ERROR: TEST FAILED</b></font> ::").append(actionDescription));
                        }
                       else
                        {
                           checkNotes="OK: check passed <br>"+checkNotes;
                           emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), true, actionDescription, checkNotes);
                           sendTestLog(QString("<font color=green><b>OK: TEST PASSED</b></font> ::").append(actionDescription));
                        };

                       //индикация нажатий
                       pal.setBrush(QPalette::Window, QBrush(QColor("pink")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                       QDRTestMaster::selectWidget->setPalette(pal);
                       selectWidget->move(targetWidget->mapToGlobal(QPoint(0,0)));

                }
            else if (action=="WaitWidget")
                 {
                    QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                    QWidget *targetWidget=waitForWidgetAppear(objectNamePath,optmap.value("timeout").toInt());
                    if (targetWidget==0)
                      {
                        sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                        //return -2;//виджет не найден - но в данном случае - надо отчитаться в лог !
                      };

                    QString checkNotes="";
                    int timeout=optmap.value("timeout").trimmed().toInt();
                    if (targetWidget==0)
                         {
                            checkNotes = "ERR: Widget not found or wait timeout out.";
                            emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                            sendTestLog(QString("<font color=red><b>ERROR: TEST FAILED. Widget not found.</b></font> ::").append(actionDescription));
                         }
                        else
                         {
                            emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), true, actionDescription, checkNotes);
                            sendTestLog(QString("<font color=green><b>OK: TEST PASSED. Widget found.</b></font> ::").append(actionDescription));
                         };

//                        //индикация нажатий
//                        pal.setBrush(QPalette::Window, QBrush(QColor("pink")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
//                        QDRTestMaster::selectWidget->setPalette(pal);
//                        selectWidget->move(targetWidget->mapToGlobal(QPoint(0,0)));

                 }

           else if (action=="KeyPress")
                {
                   QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                   QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                   if (targetWidget==0)
                     {
                       checkNotes=QString("ERROR: WIDGET NOT FOUND!");
                       emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                       sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                       return -2;//виджет не найден
                     };
                   //key=%1 text=%2 modifiers=%3 isautorepeat=%4
                   int key=optmap.value("key").trimmed().toInt();
                   QString text=optmap.value("text").trimmed();
                   if (text.contains("{ENTER}")) text.replace("{ENTER}","\n");
                   if (key==32) text = " ";

                   Qt::KeyboardModifiers modifiers= (Qt::KeyboardModifier)optmap.value("modifiers").trimmed().toInt();
                   bool isautorepeat=QDRTestMaster::string2bool(optmap.value("isautorepeat").trimmed());
                   short keyscount=1;//пока так...

                   QKeyEvent keyEvent=QKeyEvent ( QEvent::KeyPress, key,  modifiers, text, isautorepeat, keyscount);
                   //QTest::keyPress(targetWidget,(Qt::Key)key,modifiers);
                   if (!qApp->notify(targetWidget, &keyEvent))
                       {
                           sendTestLog(QString("<font color=red>ERROR: RUN FAILED: QEvent::KeyPress failed!</font> ::").append(actionDescription));
                       };

                   //индикация нажатий
                   pal.setBrush(QPalette::Window, QBrush(QColor("brown")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                   QDRTestMaster::selectWidget->setPalette(pal);
                   selectWidget->move(targetWidget->mapToGlobal(QPoint(0,0)));


                }
           else if (action=="KeyRelease")
                {
                   QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                   QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                   if (targetWidget==0)
                     {
                       checkNotes=QString("ERROR: WIDGET NOT FOUND!");
                       emit testCheckResult(QDateTime::currentDateTime().toString(dateTimeStrFormat), false, actionDescription, checkNotes);
                       sendTestLog(QString("<font color=red>ERROR: RUN FAILED: Widget not found!</font> ::").append(actionDescription));
                       return -2;//виджет не найден
                     };
                   //key=%1 text=%2 modifiers=%3 isautorepeat=%4
                   int key=optmap.value("key").trimmed().toInt();
                   QString text=optmap.value("text").trimmed();
                   if (text.contains("{ENTER}")) text.replace("{ENTER}","\n");
                   if (key==32) text = " ";

                   Qt::KeyboardModifiers modifiers=(Qt::KeyboardModifier)optmap.value("modifiers").trimmed().toInt();
                   bool isautorepeat=QDRTestMaster::string2bool(optmap.value("isautorepeat").trimmed());
                   short keyscount=1;//пока так...

                   QKeyEvent keyEvent=QKeyEvent ( QEvent::KeyRelease, key,  modifiers, text, isautorepeat, keyscount);
                   //QTest::keyRelease(targetWidget,(Qt::Key)key,modifiers);
                   //от QTest::keyPress|keyRelease придется отказаться, потому что с русскими буквами проблемы...
                   // нажатие русских букв отдает key который (видимо) не попадает в перечисление Qt::Key
                   // и функция char QTest::keyToAscii(Qt::Key key) вешает программу через QTEST_ASSERT в конце данной процедуры.
                   if (!qApp->notify(targetWidget, &keyEvent))
                        {
                            sendTestLog(QString("<font color=red>ERROR: RUN FAILED: QEvent::KeyRelease failed!</font> ::").append(actionDescription));
                        };

                   //индикация нажатий
                   pal.setBrush(QPalette::Window, QBrush(QColor("blue")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                   QDRTestMaster::selectWidget->setPalette(pal);
                   selectWidget->move(targetWidget->mapToGlobal(QPoint(0,0)));


               }



//           QDateTime::currentDateTime(),
//           namePath,
//           QString("TestValue"),
//           QString("checkid=%1 property=%2 value=\"%3\" compareType=%4 note=%5").arg(checkName).arg(propertyName).arg(propertyValue).arg("equal").arg(note)
//           );


           else return -1;//не понятная команда

          return 0;

    }


//------------------------------------------------------------
void QDRTestMaster::stopPlay(QString reason)
{
    if (infile!=0)
        {
            inStream->~QTextStream();
            infile->close();
            infile=0;
            //QMessageBox msgBox;
            //msgBox.setText("Replaying action was finished.");
            //msgBox.exec();
            QDRTestMaster::selectWidget->hide();
            QDRTestMaster::indicateWidget->hide();


            emit playFinished(QDateTime::currentDateTime().toString(dateTimeStrFormat), reason);
        };
}

//------------------------------------------------------------
//получили, надо записать.
void QDRTestMaster::rcv_recordAction(  QDateTime time,
                      QString      objectNamePath,
                      QString      action,
                      QString      actionOptions
                    )
    {

        if (controlPanelWidgetSelectingMode)
            {//режим подсветки виджета с целью выбора
                action=action.trimmed();
                if (action=="MouseMove") //для пробы отфильтруем движения мыши.
                    {

                        QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                        //QWidget *targetWidget=get_widgetByNamePath(objectNamePath);
                        //тут нам надо найти виджет самостоятельно. потому что под нами в этом режиме лежит
                        // виджет "подсветки"...
                        bool ok;
                        QDRTestMaster::selectWidget->close();//->hide();
                        QWidget *targetWidget_f=QApplication::widgetAt(optmap.value("glx").toInt(),optmap.value("gly").toInt());
                        if (targetWidget_f==0) return;
                        bool noMessages=true;
                        QString objectNamePath_f=QDRTestMaster::get_namePathOfWidget(targetWidget_f,&ok,noMessages);
                        if (!ok) return;//нельзя идентифицировтаь виджет - значит плохо..

                        //QPoint localPos=QPoint(optmap.value("x").toInt(),optmap.value("y").toInt());
                        //QPoint globPo=targetWidget->mapToGlobal(localPos);
                        QPoint globPo=QPoint(optmap.value("glx").toInt(),optmap.value("gly").toInt());
                        highLightWidgetAt(globPo.x(),globPo.y());//здесь selectWidget становится SHow

                    }
                else if (action=="MouseButtonPress")
                    { //выбрали!
                        //QDRTestMaster::selectWidget->releaseMouse();
                        QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                        bool ok;
                        selectWidget->close();//->hide();
                        if ((outfile!=0)||(infile!=0)) QDRTestMaster::indicateWidget->open();
                        QWidget *targetWidget_f=QApplication::widgetAt(optmap.value("glx").toInt(),optmap.value("gly").toInt());
                        controlPanelWidgetSelectingMode=false;
                        if (targetWidget_f==0) return;
                        QString objectNamePath_f=QDRTestMaster::get_namePathOfWidget(targetWidget_f,&ok);
                        if (!ok) return;//нельзя идентифицировтаь виджет - значит плохо..


                        QWidget *targetWidget=get_widgetByNamePath(objectNamePath_f);
                        if (targetWidget==0)
                            { //ежели мы его сейчас найти не можем... то что уж говорить о том, что бы найти его потом...
                                selectWidget->close();//->hide();
                                return;
                            };
//                        {
//                            //получим описание значения по умолчанию для заданого виджета и позиции
//                            QString optionsString=get_optionsFromWidget_useMousePos(targetWidget, QPoint(optmap.value("x").toInt(),optmap.value("y").toInt()));
//                            qDebug() << "get_optionsFromWidget_useMousePos::> build for widget next options:" << optionsString;
//                            //получим по созданному описанию - значение
//                            QString value4romWidget=get_valueFromWidget_useOptions(targetWidget,optionsString);
//                            qDebug() << "get_valueFromWidget_useOptions::> found for options next value:" << value4romWidget;
//                        }

                        QDRTestMaster::setTextOnWidget(controlPanel,"cWidget_lineEdit",objectNamePath_f);

                        selectWidget->close();//->hide();
                        rcv_getProperties();

                        if (controlPanelWidgetSelectingSubMode==2) //for waitAndCheck
                            {
                                controlPanelWidgetSelectingSubMode=0;
                                rcv_controlPanelAddWait();
                            };

                        if (controlPanelWidgetSelectingSubMode==3) //for Adv Default Check
                            { //расширенный testValue
                                controlPanelWidgetSelectingSubMode=0;
                                QString actionOptions=get_defaultOptionsFromWidget_useMousePos(targetWidget, QPoint(optmap.value("x").toInt(),optmap.value("y").toInt()));
                                QString namePath=QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,"cWidget_lineEdit");
                                rcv_recordAction(
                                            QDateTime::currentDateTime(),
                                            namePath,
                                            QString("TestValue"),
                                            actionOptions
                                        );//compareType(s) are: equal more less in notin contain notcontain

                            };
                        emit setSelectWidgetText(" ");

                    };
                return;
            };

        if (outfile!=0)
            {//если ведем запись
                QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));
                bool ok;
                  {
                    if (action.trimmed()=="MouseMove")
                      { //отобразим - распознаем ли мы виджет под курсором.

                        QWidget *targetWidget_f=QApplication::widgetAt(optmap.value("glx").toInt(),optmap.value("gly").toInt());
                        if (targetWidget_f==0) return;
                        QString objectNamePath_f=QDRTestMaster::get_namePathOfWidget(targetWidget_f,&ok);

                        QPalette pal = QPalette();
                        pal.setBrush(QPalette::Window, QBrush(QColor(255,255,255,0))); //QBrush(QColor("green")) );//QBrush(QPixmap( ":/images/bg1.png"))
                        if (ok)
                            pal.setBrush(QPalette::Window, QBrush(QPixmap( ":/action_succsess")) ); //QBrush(QColor("green")) );//QBrush(QPixmap( ":/images/bg1.png"))
                          else
                            pal.setBrush(QPalette::Window, QBrush(QPixmap( ":/action_fail")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                        QDRTestMaster::indicateWidget->setPalette(pal);

                        QDRTestMaster::indicateWidget->move(optmap.value("glx").toInt()+30,optmap.value("gly").toInt()+5);
                      }//if (action=="MouseMove")
                    else
                        if (action.trimmed()=="MouseButtonPress")
                          { //отобразим что мы записали нажатие.
                            QPalette pal = QPalette();
                            pal.setBrush(QPalette::Window, QBrush(QColor("yellow")) ); //QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
                            QDRTestMaster::indicateWidget->setPalette(pal);
                            QDRTestMaster::indicateWidget->move(optmap.value("glx").toInt()+30,optmap.value("gly").toInt()+5);
                          };
                      ;// selectWidget->hide();

                  };//if (outfile!=0)
            };
        QString separator=";";
        QString rez="";
        rez += " time="+time.toString(dateTimeStrFormat)+separator;
        rez += " action="+action+separator;
        rez += " object="+QDRTestMaster::escapeCharacters(objectNamePath,separator)+separator;
        rez += " options="+QDRTestMaster::escapeCharacters(actionOptions,separator)+""+separator;//Тут даже если будет равно внутри то только первое равно будет воспринято как разделитель.
        rez += " "+QString("\n");//+endl;

        if (   (compressMouseMoves && (outfile!=0))
              and
               (lastRecivedActionType==action.trimmed())
              and
               (lastRecivedActionType=="MouseMove")
            )
              {
                    lastRecivedAction=rez; //used then recording
                    lastRecivedActionType=action.trimmed(); //used then recording
                    return;
              }
            else
              {
                if  (
                        (outfile!=0)
                       and
                        (!lastRecivedAction.isEmpty())
                    )

                    {
                        (*outStream) << lastRecivedAction;
                        sendTestLog(QString("added: %1").arg(lastRecivedAction));
                        //qDebug() << "(*outStream) :: lastRecivedAction; "<< lastRecivedAction;
                    }
              };

        lastRecivedAction=""; //used then recording
        lastRecivedActionType=action.trimmed(); //used then recording

        if (outfile!=0)
            {
                (*outStream) << rez;
                sendTestLog(QString("added: %1").arg(rez));
                //qDebug() << "(*outStream) :: rez; "<< rez;
            }
          else
            {
                //qDebug() << "INFO:QDRTestMaster::rcv_userAction()[00076] rez=" << rez;
            };
        //qDebug() << "INFO:QDRTestMaster::rcv_userAction()[00080] rez=" << rez;

    };

void QDRTestMaster::highLightWidgetAt(int glX, int glY)
  {
    selectWidget->close();//->hide();

    QWidget *underWidget=QApplication::widgetAt(glX,glY);
    //QPushButton *selectWidgetB = qFindChild<QPushButton *> (cControlPanel, "selectWidget_pushButton");
    if (underWidget==0) return;

    selectWidget->resize(underWidget->size());
    selectWidget->move(underWidget->mapToGlobal( QPoint(0,0) ));

    selectWidget->open();//->show();


  }



//------------------------------------------------------------
// отдает "путь имен" виджетов, наичная от коненного-обще-родительского (у которого parent==0)
// по данной строке мы будем идентифицировать виджет.
//
// 2010.09.10: если виджет не имеет имени - пробуем идентифицировать его по координатам (но это только для не корневых виджетов)
// элемент который идентифицируется по координатам записывается так:
// /:XY:12:34/
// где 12 - x координата(число) 34 - y координата(число)
// где точка - это точка на виджете. скажем коорднаты +2 пикселя
//
// 2010.09.10+: корневой вджет можно идентифицировать по заголовку
// /:TITLE:IS:window title/
// /:TITLE:STARTS:window/
// /:TITLE:ENDS:title/
// /:TITLE:CONTAINS:dow tit/
//
// 2010.09.10+: единственный неименованный виджет можно и пропустить наверное
// /:ONENONAMEDCHILD/

//
// [static]
QString QDRTestMaster::get_namePathOfWidget(QWidget *_cWidget, bool *_ok, bool noMessages)
    {
        QString cRez="", cPName="";
        QWidget *cWidget, *cParent;
        cWidget = _cWidget;
        bool hasSlash=false, hasNonamed=false;

        if (_cWidget==0)
            {
                if (_ok!=0) *_ok=false;
                return QString();
            };
        cRez="";
        cPName=cWidget->objectName();
        cParent=cWidget;
        while ( cParent!=0 )
            {// внимание! нельзя использовать в именах символ слеша. т.е. мы работать в этом случае не будем.
             // но пока не понятно что потом с этим сделать...
                if (cPName.contains("/"))
                    {
                        //qDebug() << tr("ERROR: QDrApplication::get_namePathOfWidget()[00030] В именах виджетов используются символы слеша (/)! ") ;
                        //cRez="{ERROR:useSlashes:"+cPName+"{"+cParent->metaObject()->className()+"}}/"+cRez;
                        cPName="{ERROR:useSlashes:"+cPName+"{"+cParent->metaObject()->className()+"}}";
                        hasSlash=true;
                    }
                else if (cPName.isEmpty())
                    {
                        //todo:ПОПРОБУЕМ ТУТ ПОНЯТЬ - ЕСЛИ НЕИМЕНОВАННЫЙ ВИДЖЕТ - ЕДИНСТВЕННЫЙ СРЕДИ ПОТОМКОВ СВОЕГО РОДИТЕЛЯ - ТО И КАК БЫ ПУСТЬ...
                        // todo!
                        //qDebug() << tr("ERROR: QDrApplication::get_namePathOfWidget()[00033] Обнаружено пустое имя виджета! Остаток пути: .../") << cRez;
                        //2010.09.10 пока просто пропишем его как /:XY:x:y

                        if (cParent->parentWidget()!=0)
                            {

                                QPoint wDot=cParent->mapTo(cParent->parentWidget(),QPoint(2,2));
                                cPName = QString(":XY:%1:%2:{%3}").arg(wDot.x()).arg(wDot.y()).arg(cParent->metaObject()->className());
                            }
                        else
                            {   //если у нас нет родителя - то наверняка
                                if (!cParent->windowTitle().isEmpty()) //// /:TITLE:IS:window title/
                                    {
                                        QString title=cParent->windowTitle().trimmed();
                                        int count=0;
                                        foreach (QWidget *widget, QApplication::topLevelWidgets())
                                            {//поищем ещё корневые виджеты с таким именем
                                                if (widget->windowTitle().trimmed()==title)
                                                    count++;
                                            };
                                        if (count==1)// блин, а что делать если ==0?! ))))
                                            {
                                                cPName = QString(":TITLE:IS:%1:{%2}").arg(title).arg(cParent->metaObject()->className());
                                            };
                                    };
                            };
                        if (cPName.isEmpty())
                            {
                                cPName=QString("{ERROR:nonamed{%1}}").arg(cParent->metaObject()->className());
                                hasNonamed=true;
                            };
                    };
                //else
                  {
                    if (cRez.isEmpty())
                     cRez=cPName;
                    else
                     cRez=cPName+"/"+cRez;
                  };
                //заметка:
                //по идее, если cParent->parentWidget()==0, то cParent должен быть в QApplication::topLevelWidgets())
                // пока не проверял...))
                cParent=cParent->parentWidget();
                if (cParent!=0) cPName = cParent->objectName();
            };
        if (_ok!=0)
            *_ok=true;

       if (hasNonamed)
            {
               QString message=QString("ERROR: QDrApplication::get_namePathOfWidget()[00033] Обнаружено пустое имя виджета! : %1").arg(cRez);
               if (!noMessages) QDRTestMaster::st_sendTestLog("<font color=blue>"+message+"</font>");
               if (!noMessages) qDebug() << message;
               if (_ok!=0) *_ok=false;
            };
       if (hasSlash)
            {
                QString message=QString("ERROR: QDrApplication::get_namePathOfWidget()[00030] В именах виджетов используются символы слеша (/)! : %1").arg(cRez);
                if (!noMessages) QDRTestMaster::st_sendTestLog("<font color=blue>"+message+"</font>");
                if (!noMessages) qDebug() << message;
                if (_ok!=0)
                    *_ok=false;
            };


        return cRez;
    }

//------------------------------------------------------------
// отдает "Виджет" соответствующий "пути имени"
// 2010.08.31 фича: если виджет не именован - то может найти по заголовку? спасет для различных автогенерируемых всплывающих модальных окошек-вопросов...
// [static]
QWidget *QDRTestMaster::get_widgetByNamePath(QString namePathOfWidget)
    {
        QStringList objNames=namePathOfWidget.split("/");
        QStringList subObjNames;
        QObject *someObject;

        //надо найти корневой виджет, от которого начинается цепочка имен
        QString cName, fPath;
        QString rootName=objNames.takeFirst();
        QWidget *cWidget = 0;
        bool isName=!rootName.startsWith(":");
        subObjNames = rootName.split(":");
        foreach (QWidget *widget, QApplication::topLevelWidgets())
            {
                if (isName)
                    {
                        if (widget->objectName()==rootName)
                            {
                                cWidget=widget;
                                break;
                            };
                    }
                  else
                    { //корневой виджет можно по заголовку искать.
                        if (subObjNames.at(1)=="TITLE")
                            {
                                /*
                                 /:TITLE:IS:window title/
                                 /:TITLE:STARTS:window/
                                 /:TITLE:ENDS:title/
                                 /:TITLE:CONTAINS:dow tit/
                                */
                                if (subObjNames.at(2)=="IS") // пока только полное соответствие
                                   if (widget->windowTitle()==subObjNames.at(3))
                                     {
                                       cWidget=widget;
                                       break;
                                     };
                            };
                    };
            };

        if (cWidget==0)
            {
                QString message=QString("ERROR: QDRTestMaster::get_WidgetByNamePath()[00420] не найден корневой виджет %1  в пути %2").arg(rootName).arg(namePathOfWidget);
                QDRTestMaster::st_sendTestLog("<font color=blue>"+message+"</font>");
                qDebug() << message;
                return 0;
            };

        fPath=rootName;

        while ((objNames.size()>0) && (cWidget!=0))
            {
                cName=objNames.takeFirst();
                if (cName.startsWith(":"))
                    {//значит у нас указание а не имя...
                        subObjNames = cName.split(":");
                        if (subObjNames.at(1)=="XY")
                            { //":XY:%1:%2" - это указание найти виджет по координатам его точки (вообще 2х2)
                                   int wx = subObjNames.at(2).toInt();
                                   int wy = subObjNames.at(3).toInt();
                                   someObject=cWidget->childAt(wx,wy);
                            };
                    }
                else
                    {
                        someObject = qFindChild<QObject *> (cWidget, cName ); //для MSVC
                    };

                if ( (someObject!=0) && (someObject->isWidgetType() ))
                    {
                        cWidget=(QWidget*)(someObject);
                        fPath += "/"+cName;
                    }
                   else
                    {
                       cWidget=0;
                    };
            };

        if (cWidget==0)
            {
                QString message=QString("ERROR: QDRTestMaster::get_WidgetByNamePath()[00450] не найден виджет %1 + %2 в пути %3").arg(fPath).arg(cName).arg(namePathOfWidget);
                QDRTestMaster::st_sendTestLog("<font color=blue>"+message+"</font>");
                qDebug() << message;
                return 0;
            };
        return cWidget;
    }


//-----------------------------------------------------------------
//получаем значение виджета и описываем свойство по умолчанию в зависимости от типа виджета
//[static]
QString QDRTestMaster::get_valueFromWidget_useOptions(QWidget *_widget, QString actionOptions)
{
    QWidget *widget=_widget;
    QString ret;
    const QMetaObject *metaObj=widget->metaObject();
    QString widgetClass=metaObj->className();

    QStringMap optmap=QDRTestMaster::cleverSplitToMap(actionOptions,QString(" "));

    QString valueOnVidget=QString();

    if (widgetClass=="QWidget")
        { //так иногда бывает когда мы клацаем по агрегированому виджету QTreeWidget
          //потому попробуем выйти на родителя и получить более осмысленный результат
                if (widget->parentWidget()!=0)
                    {
                            QString wClass2=widget->parentWidget()->metaObject()->className();
                            if ((wClass2=="QTreeWidget")||(wClass2=="QTextEdit"))
                                {
                                  widget=widget->parentWidget();
                                  widgetClass=wClass2;
                                  metaObj=widget->metaObject();
                                };
                    };
        };

    QString checkid=optmap.value("checkid").trimmed();
    QString property=optmap.value("property").trimmed();
    QString value=optmap.value("value").trimmed();
    QString compareType=optmap.value("compareType").trimmed();
    QString note=optmap.value("note").trimmed();
    bool isFuncton=property.endsWith("()");


    //тут вообще можно/надо ткнуться в DOM структуру но это потом
    if (widgetClass=="QTextEdit")
        {
            QString valueOnVidget;
            if (!isFuncton)
              {
                valueOnVidget=widget->property(property.toLocal8Bit().constData()).toString();
              }
            else
              {
                if (property=="toHtml()")
                    {
                        valueOnVidget=((QTextEdit*)widget)->toHtml();
                    };
                if (property=="toPlainText()")
                    {
                        valueOnVidget=((QTextEdit*)widget)->toPlainText();
                    };

              };
            //ret=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5").arg("QL").arg("toHtml()").arg( textS ).arg("equal").arg("no_notes");
            ret=valueOnVidget;

        } //if (widgetClass=="QTextEdit")

    //с "таблице-образными" делаем так:
    //по координатам вычисляем ячейку и вытаскиваем её содержимое в строку
    else if (widgetClass=="QTreeWidget")
        {
            QString valueOnVidget;
            if (!isFuncton)
              {
                valueOnVidget=widget->property(property.toLocal8Bit().constData()).toString();
              }
            else
              {
                if (property=="@getCellAtRC()")
                    {
                        int cRow=0;
                        valueOnVidget=QString();
                        int tRow=optmap.value("row").trimmed().toInt();
                        int tCol=optmap.value("col").trimmed().toInt();
                        QTreeWidgetItem *cTreeWI=((QTreeWidget*)widget)->itemAt(1,1);
                        while ((cRow<tRow) and (cTreeWI!=0))
                            {
                              cRow++;
                              cTreeWI=((QTreeWidget*)widget)->itemBelow(cTreeWI);
                            };

                        if (cTreeWI!=0)
                            {
                                valueOnVidget=cTreeWI->text(tCol);
                            };
                        //ret=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5 row=%6 col=%7 x=%8 y=%9 ").arg("QL").arg("@getCellAtRC()").arg( textS ).arg("equal").arg("no_notes").arg(row).arg(col).arg(localPos.x()).arg(localPos.y());
                        ret=valueOnVidget;
                    };
              };
        }   //if (widgetClass=="QTreeWidget")
    else // for others
        {
            QString valueOnVidget;
            if (!isFuncton)
              {
                valueOnVidget=widget->property(property.toLocal8Bit().constData()).toString();
              }
            else
              {
                if (property=="@callScript()") //вызываем функцию-обработчие нестандартных ситуаций
                    { /*передаем туда ссылку на класс обмена данными - содержит список опций, ссылку на виджет,... ещё?*/
                        //TODO!
                    };
              };
            ret=valueOnVidget;
        };
            // the same and for others
            //    if (widgetClass=="QLabel")
            //    if (widgetClass=="QLineEdit")
            //    if (widgetClass=="QPushButton")

    //qDebug() << "QDRTestMaster::get_defaultValue4checkFromWidget() ::=>" << ret;
    return ret;

}

//-----------------------------------------------------------------
//выбираем значение виджета и описываем свойство по умолчанию в зависимости от типа виджета
//[static]
//сделать тут возврат в QStringMap? что бы это выносить на панель - а там редактировать или добавлять в проверку.
QString QDRTestMaster::get_defaultOptionsFromWidget_useMousePos(QWidget *_widget, QPoint localPos)
{
    QWidget *widget=_widget;
    QString ret;
    const QMetaObject *metaObj=widget->metaObject();
    QString widgetClass=metaObj->className();

    if (widgetClass=="QWidget")
        { //так иногда бывает когда мы клацаем по агрегированому виджету QTreeWidget
          //потому попробуем выйти на родителя и получить более осмысленный результат
            if (widget->parentWidget()!=0)
                {
                    QString wClass2=widget->parentWidget()->metaObject()->className();
                    if ((wClass2=="QTreeWidget")||(wClass2=="QTextEdit"))
                        {
                          widget=widget->parentWidget();
                          widgetClass=wClass2;
                          metaObj=widget->metaObject();
                        };
                };

        };

    if (widgetClass=="QLabel")
        { ret=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5").arg("QL").arg("text").arg(widget->property("text").toString()).arg("equal").arg("no_notes");
        };

    if (widgetClass=="QLineEdit")
        { ret=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5").arg("QL").arg("text").arg(widget->property("text").toString()).arg("equal").arg("no_notes");
        };

    if (widgetClass=="QPushButton")
        { ret=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5").arg("QL").arg("text").arg(widget->property("text").toString()).arg("equal").arg("no_notes");
        };

    //тут вообще можно/надо ткнуться в DOM структуру но это потом
    if (widgetClass=="QTextEdit")
        {   //QString textS = ((QTextEdit*)widget)->toHtml();
            QString textS = ((QTextEdit*)widget)->toPlainText();
            textS=QDRTestMaster::escapeAndPrepareValueStringForRecording(textS);
//            QDRTestMaster::escapeCharacters(textS," ");
//            QDRTestMaster::escapeCharacters(textS,"\"");
//            QDRTestMaster::escapeCharacters(textS,";");
//            QDRTestMaster::escapeCharacters(textS,"#");
//            QDRTestMaster::escapeCharacters(textS,"\\");
////            ret=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5").arg("QL").arg("toHtml()").arg( textS ).arg("equal").arg("no_notes");
            ret=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5").arg("QL").arg("toPlainText()").arg( textS ).arg("equal").arg("no_notes");
        };

    //с "таблице-образными" делаем так:
    //по координатам вычисляем ячейку и вытаскиваем её содержимое в строку
    if (widgetClass=="QTreeWidget")
        {
            QTreeWidgetItem *treeWI=((QTreeWidget*)widget)->itemAt(localPos);
            int col = ((QTreeWidget*)widget)->columnAt ( localPos.x() );
            QString textS=treeWI->text(col);
            textS=QDRTestMaster::escapeCharacters(textS," ");
            textS=QDRTestMaster::escapeCharacters(textS,";");
            textS=QDRTestMaster::escapeCharacters(textS,"#");
            textS=QDRTestMaster::escapeCharacters(textS,"\\");

            QTreeWidgetItem *cTreeWI=treeWI;
            int row=-1;
            while (cTreeWI!=0)
                { row++;
                  cTreeWI=((QTreeWidget*)widget)->itemAbove(cTreeWI);
                };

            ret=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5 row=%6 col=%7 x=%8 y=%9 ").arg("QL").arg("@getCellAtRC()").arg( textS ).arg("equal").arg("no_notes").arg(row).arg(col).arg(localPos.x()).arg(localPos.y());

        };
    //qDebug() << "QDRTestMaster::get_defaultValue4checkFromWidget() ::=>" << ret;
    return ret;

}
//-----------------------------------------------------------------
/*
получить объект, отображение которого отражено на виджете в заданных координатах
необходимо для QTreeView - На выходе - QTreeElenent или ячейка

(надо ввести понятие как описание суб-объекта?)
*/
//NOT USED
s_subObjectDescription QDRTestMaster::get_objectAndSubNamePathForWidgetDotEvent(QWidget *_widget, int _x,int _y)
    {
//        s_subObjectDescription retRez;
//        retRez.object=0;
//        QString className=_widget->metaObject()->className();

//        if (className=="QTreeView")
//            {
//                int column=((QTreeWidget*)_widget)->columnAt( _x );
//                QTreeWidgetItem *item=((QTreeWidget*)_widget)->itemAt(_x,_y);

//                retRez.object=(QObject*)item;
//                retRez.objectType="QTreeWidgetItem";
//                //QWidget * QTreeWidget::itemWidget ( QTreeWidgetItem * item, int column ) const
//                //идентифицировать по индексу? QTreeWidgetItem * QTreeWidget::itemFromIndex ( const QModelIndex & index ) const
//                //retRez.
//                retRez.options="text="+item->text(column)+";";
//            };


    }
//-----------------------------------------------------------------
//NOT USED yet
QObject *QDRTestMaster::get_SubNamePathForWidget(QWidget *_widget, QString _subNamePath)
    {

    }

//-----------------------------------------------------------------
//проверяем только(!) в непосредственном подчинении а не глобально!!!!
//[static]
QString QDRTestMaster::get_uniqueNameForChildWidget(QString nameOfWidget, QWidget *parent)
{
    //теперь надо придумать имя окошку и удостовериться, что таких окон более нет.

    QObject *someObject;
    int counter=2;
    QString windowName2;
    QString windowName = nameOfWidget;
    //if (windowName.isEmplty()) windowName = "_";
    //windowName = ""+windowName;
    windowName2 = windowName;

    QWidgetList widgetList;
    if (parent==0)
        {
           widgetList=QApplication::topLevelWidgets();
        }
       else
        {
           //widgetList=widgetList.append(parent);
           widgetList=qFindChildren<QWidget *> (parent);// windowName2 );
        };

    QStringList widgetNames;
    foreach (QWidget *widget, widgetList)
        {
            if (widget->parentWidget()!=parent) continue; //нам нужны только непосредственного подчинения
            widgetNames.append(widget->objectName());
        };

    //возможно нижеследующее стоит заменить на поиск в списке виджетов от коре-апп? все быстрее будет...
    while (widgetNames.contains(windowName2))
        {
           windowName2=QString("%1(%2)").arg(windowName).arg(counter);
           counter++;
        };
    windowName=windowName2;
    return windowName;
}

//------------------------------------------------------------------
QString QDRTestMaster::QtMouseButton2String(Qt::MouseButton button)
    {
        if (button==Qt::LeftButton) return "LeftButton";
        if (button==Qt::RightButton) return "RightButton";
        if (button==Qt::MidButton) return "MidButton";
        if (button==Qt::XButton1) return "XButton1";
        if (button==Qt::XButton2) return "XButton2";
        //if (button==Qt::NoButton)
        return "NoButton";
    }
//------------------------------------------------------------------
Qt::MouseButton QDRTestMaster::String2QtMouseButton(QString button)
    {
        if (button=="LeftButton") return Qt::LeftButton;
        if (button=="RightButton") return Qt::RightButton;
        if (button=="MidButton") return Qt::MidButton;
        if (button=="XButton1") return Qt::XButton1;
        if (button=="XButton2") return Qt::XButton2;
        //if (button=="NoButton")
        return Qt::NoButton;
    }
//------------------------------------------------------------------
bool QDRTestMaster::string2bool(QString str)
    {
        if (str.toLower()=="true") return true;
        if (str.toLower()=="false") return false;
        return false;
    }
//------------------------------------------------------------------
QString QDRTestMaster::bool2string(bool str)
    {
        if (str) return "true";
        if (!str) return "false";
        return "false";
    }
//------------------------------------------------------------
//Показываем маленькое окошко в заголовке которое по нажатию вызывает панель управления
// и собственно показывает что МастерТестов подключен
QWidget *QDRTestMaster::get_agentPanel()
    {

      if (QDRTestMaster::agentPanel==0)
        {
            QDRTestMaster::agentPanel = new QWidget();
            QDRTestMaster::agentPanel->setWindowOpacity(0.9);
            QDRTestMaster::agentPanel->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint|Qt::Tool);

            QLabel *label=new QLabel( QDRTestMaster::agentPanel);
            label->move(3,0);
            label->setText(QString("<b>QDroid TestMaster [v.%1] is online.</b> [<a href=\"#ControlPanel(noKeyOperation)\">Control Panel</a>]").arg(__version));

            QPalette pal = QPalette();
            //pal.setBrush(QPalette::Window, QBrush(QColor(0x81,0xfa,0x00)) );//QBrush(QPixmap( ":/images/bg1.png"))
            pal.setBrush(QPalette::Window, QBrush(QColor(0xff,0xff,0x00)) );//QBrush(QPixmap( ":/images/bg1.png"))


            QDRTestMaster::agentPanel->setPalette(pal);
            QDRTestMaster::agentPanel->resize(350,14);
            QDRTestMaster::agentPanel->move(200,2);
            //QDRTestMaster::agentPanel->show();
            QObject::connect(label,SIGNAL(linkActivated(QString)),this,SLOT(rcv_agentPanel_linksActivated(QString)));

        };

    return QDRTestMaster::agentPanel;

    }
//------------------------------------------------------------
void QDRTestMaster::rcv_agentPanel_linksActivated(QString link)
    {
        if  (link.startsWith("#ControlPanel"))
            {
                //это все для системы фильтрации от автоповторов и "эхо-событий" от родительских виджетов и др.
                if (link.contains("(keyReleased)"))
                    {
                        QDRTestMaster::controlPanel->setProperty("inKeyPressOperation",false);
                        return;
                    };
                if (QDRTestMaster::controlPanel->property("inKeyPressOperation").toBool()==true)
                    return; //значит это нажатие мы уже отработали. пока не отпустят - мы не реагируем.

                qDebug() << "rcv_agentPanel_linksActivated()[01246] #ControlPanel";
                if (!link.contains("(noKeyOperation)"))
                    QDRTestMaster::controlPanel->setProperty("inKeyPressOperation",true);

                if (QDRTestMaster::controlPanel->isVisible())
                     {
                       qDebug() << "rcv_agentPanel_linksActivated()[01249] #ControlPanel :: close";
                       //QDRTestMaster::controlPanel->hide();
                       QDRTestMaster::controlPanel->close();
                       //emit close_ControlPanel();
                     }
                    else
                     {
                        if (link.endsWith("::toCursorPos"))
                            {
                                QPoint curPos=QCursor::pos();
                                QDRTestMaster::controlPanel->move(curPos.x()-10,curPos.y()-10);
                            }
                          else
                            {
                              QPoint curPos=QDRTestMaster::agentPanel->pos();
                              QDRTestMaster::controlPanel->move(curPos.x(),curPos.y()+QDRTestMaster::agentPanel->size().height());
                            };
                        qDebug() << "rcv_agentPanel_linksActivated()[01264] #ControlPanel :: exec";
                        //((QDialog*)QDRTestMaster::controlPanel)->setVisible(true);
                        ((QDialog*)QDRTestMaster::controlPanel)->open();
                        //emit exec_ControlPanel();
                     };
            };

        if  (link=="@SelectWidget")
            {
                if (!controlPanelWidgetSelectingMode)
                    rcv_controlPanelWSelect();
            };

        if  (link=="@SelectWidget4WaitAndCheck")
            {
                int forWaitAndCheckMode=2;
                if (!controlPanelWidgetSelectingMode)
                    rcv_controlPanelWSelect(forWaitAndCheckMode);
            };

        if  (link=="@SelectWidget4AdvancedDefaultValueCheck")
            {
                int AdvancedDefaultValueCheck=3;
                if (!controlPanelWidgetSelectingMode)
                    rcv_controlPanelWSelect(AdvancedDefaultValueCheck);
            };

        if  (link=="@StopAction")
            {
                rcv_controlPanelStop();
            };
    }
//------------------------------------------------------------
QWidget *QDRTestMaster::get_controlPanel()
{
    if (QDRTestMaster::controlPanel==0)
        {
            bool rez;
            //QFile file("./../../../classes/QDRTestMaster_controlPanel.ui");//очень не хорошо потому что ui в исходниках а мы в рантайме - в бинарниках
            //bool rez=file.open(QFile::ReadOnly);
            QDRTestMaster_controlPanel *cControlPanel = new QDRTestMaster_controlPanel();//uiloader.load(&file);
            //file.close();

            QPushButton *recButton = qFindChild<QPushButton *> (cControlPanel, "rec_pushButton");
            QPushButton *playButton = qFindChild<QPushButton *> (cControlPanel, "play_pushButton");
            QPushButton *stopButton = qFindChild<QPushButton *> (cControlPanel, "stop_pushButton");
            QPushButton *selectWidgetButton = qFindChild<QPushButton *> (cControlPanel, "selectWidget_pushButton");
            QPushButton *getPropertiesButton = qFindChild<QPushButton *> (cControlPanel, "getProperties_pushButton");
            QPushButton *addTestButton = qFindChild<QPushButton *> (cControlPanel, "addTest_pushButton");
            QPushButton *addWaitButton = qFindChild<QPushButton *> (cControlPanel, "addWait_pushButton");
            QPushButton *fileOpenButton = qFindChild<QPushButton *> (cControlPanel, "fileOpen_pushButton");

            QLineEdit *fileLineEdit = qFindChild<QLineEdit *> (cControlPanel, "filename_lineEdit");
            QLabel *statusLabel = qFindChild<QLabel *> (cControlPanel, "status_label");
            QTextEdit *logView = qFindChild<QTextEdit *> (cControlPanel, "log_textEdit");;
            QComboBox *cBoxProperties= qFindChild<QComboBox *> (cControlPanel, "property_comboBox");
            QComboBox *cBoxCompareType= qFindChild<QComboBox *> (cControlPanel, "compareType_comboBox");


            fileLineEdit->setText("userActionsRecord.posb.rec.2play.txt");
            statusLabel->setText("...");


            rez=connect(eventFilter, SIGNAL(sendLog(QString)), logView, SLOT(append(QString)) );
            rez=connect(this, SIGNAL(sendTestLog(QString)), logView, SLOT(append(QString)) );
            rez=connect(this, SIGNAL(clearTestLog()), logView, SLOT(clear()) );

            rez=connect(recButton,SIGNAL(clicked()),this,SLOT(rcv_controlPanelRecord()));
            rez=connect(playButton,SIGNAL(clicked()),this,SLOT(rcv_controlPanelPlay()));
            rez=connect(stopButton,SIGNAL(clicked()),this,SLOT(rcv_controlPanelStop()));
            rez=connect(selectWidgetButton,SIGNAL(clicked()),this,SLOT(rcv_controlPanelWSelect()));
            rez=connect(getPropertiesButton,SIGNAL(clicked()),this,SLOT(rcv_getProperties()));
            rez=connect(addTestButton,SIGNAL(clicked()),this,SLOT(rcv_controlPanelAddTest()));
            rez=connect(addWaitButton,SIGNAL(clicked()),this,SLOT(rcv_controlPanelAddWait()));
            rez=connect(fileOpenButton,SIGNAL(clicked()),this,SLOT(rcv_controlPanelFileOpen()));


            rez=connect(cBoxProperties,SIGNAL(currentIndexChanged(QString)),this,SLOT(rcv_controlPanel_propChanged(QString)));


            cControlPanel->setObjectName("TestWizardControlPanel");
//            cControlPanel->setObjectName("TestWizardControlPanel");
//            QDRTestMaster::controlPanel= cControlPanel;
            QDRTestMaster::controlPanel = new QDialog();
            cControlPanel->setParent(QDRTestMaster::controlPanel);
            QBoxLayout *newBL=new QBoxLayout(QBoxLayout::TopToBottom, QDRTestMaster::controlPanel);
            newBL->addWidget(cControlPanel,100);
            QDRTestMaster::controlPanel->setLayout(newBL);
            QDRTestMaster::controlPanel->setObjectName("QDialogFrame4TestP");

            eventFilter->filteredWindowName="QDialogFrame4TestP";

            QDRTestMaster::controlPanel->setWindowFlags(Qt::WindowStaysOnTopHint);//|Qt::Tool
            QDRTestMaster::controlPanel->setWindowModality(Qt::WindowModal);

            //rez=connect(this, SIGNAL(exec_ControlPanel()), QDRTestMaster::controlPanel, SLOT(exec()), Qt::QueuedConnection );
            //rez=connect(this, SIGNAL(close_ControlPanel()), QDRTestMaster::controlPanel, SLOT(hide()), Qt::QueuedConnection );

        };

    return QDRTestMaster::controlPanel;
}

//------------------------------------------------------------
int QDRTestMaster::rcv_controlPanelFileOpen()
{
    QLineEdit *fileLineEdit = qFindChild<QLineEdit *> (QDRTestMaster::controlPanel, "filename_lineEdit");
    QString fileName = QFileDialog::getOpenFileName(0, tr("Открыть сценарий"), ".", tr("Файл сценария QDroid TestMaster(*.tms.txt)"));

    QFile prbFile(fileName);
    if (!prbFile.open(QIODevice::ReadOnly | QIODevice::Text))
        {
            fileName="";
        }
        else
        {
            prbFile.close();
        };

    if (!fileName.isEmpty())
        fileLineEdit->setText(fileName);
}

//------------------------------------------------------------
int QDRTestMaster::rcv_controlPanelRecord()
{
    if ((infile!=0) || (outfile!=0)) return -2;//currently in action

    QLineEdit *fileLineEdit = qFindChild<QLineEdit *> (get_controlPanel(), "filename_lineEdit");
    QLabel *statusLabel = qFindChild<QLabel *> (get_controlPanel(), "status_label");
    //qDebug() << "int QDRTestMaster::rcv_controlPanelRecord()";
    if (startRecord(fileLineEdit->text().trimmed())>=0)
        {
            statusLabel->setText("RECORDING");
            return -1;
        }
      else
        {
            statusLabel->setText("<rec. failed>");
            return 0;
        };

    return 0;

}

//------------------------------------------------------------
int QDRTestMaster::rcv_controlPanelPlay()
{

    if ((infile!=0) || (outfile!=0)) return -2;//currently in action

    QLineEdit *fileLineEdit = qFindChild<QLineEdit *> (get_controlPanel(), "filename_lineEdit");
    QLabel *statusLabel = qFindChild<QLabel *> (get_controlPanel(), "status_label");
    //qDebug() << "int QDRTestMaster::rcv_controlPanelPlay()";
    if (startPlay(fileLineEdit->text().trimmed()))
        {
            statusLabel->setText("PLAYING");
            return -1;
        }
      else
        {
            statusLabel->setText("<play failed>");
            return 0;
        };

    return 0;
}

//------------------------------------------------------------
int QDRTestMaster::rcv_controlPanelStop()
{
    if ((infile==0) && (outfile==0)) return -3;//currently NOT in action

    QLineEdit *fileLineEdit = qFindChild<QLineEdit *> (get_controlPanel(), "filename_lineEdit");
    QLabel *statusLabel = qFindChild<QLabel *> (get_controlPanel(), "status_label");
    QDRTestMaster::indicateWidget->hide();
    if (infile!=0)
        stopPlay();
    if (outfile!=0)
        stopRecord();

    statusLabel->setText("STOPPED");
    qDebug() << "int QDRTestMaster::rcv_controlPanelStop()";
    return 0;
}


//------------------------------------------------------------
int QDRTestMaster::rcv_controlPanelWSelect(int subMode)
        {
            //if ((infile==0) && (outfile==0)) return -3;//currently NOT in action
            controlPanelWidgetSelectingMode = true;
            controlPanelWidgetSelectingSubMode=subMode;
            //QDRTestMaster::selectWidget->grabMouse();

            if (subMode==0)
                emit setSelectWidgetText("<b>Cвойства виджета.</b>");
            if (subMode==2)
                emit setSelectWidgetText("<b>Наличие виджета.</b>");
            if (subMode==3)
                emit setSelectWidgetText("<b>(X*Y) виджета.</b>");

            QPalette pal = QPalette();
            pal.setBrush(QPalette::Window, QBrush(QColor("red")) );//QBrush(QPixmap( ":/images/bg1.png"))
            QDRTestMaster::selectWidget->setPalette(pal);
            QDRTestMaster::indicateWidget->close();

            return 0;
        }
//------------------------------------------------------------
int QDRTestMaster::rcv_getProperties()
        {
            QWidget *cwidget=get_widgetByNamePath( QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,QString("cWidget_lineEdit") ));
            if (cwidget==0) return -1;

            const QMetaObject *cwidgetMO=cwidget->metaObject();

            QStringList properties;
            for(int i = 0; i < cwidgetMO->propertyCount(); ++i)//а если хотим только ЕГО СОБСТВЕННЫЕ свойства - то надо с widgetMO->propertyOffset()
                properties << QString::fromLatin1(cwidgetMO->property(i).name());

            QComboBox *cBoxProperties= qFindChild<QComboBox *> (QDRTestMaster::controlPanel, "property_comboBox");
            if (cBoxProperties==0) return -100;

            cBoxProperties->clear();
            cBoxProperties->insertItems(0,properties);

            // ( int index, const QStringList & list

            return 0;
        }
//------------------------------------------------------------
int QDRTestMaster::rcv_controlPanel_propChanged(QString propName)
        {
            QWidget *cwidget=get_widgetByNamePath( QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,QString("cWidget_lineEdit") ));
            if (cwidget==0) return -1;

            //QString actionOptions=QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5 row=%6 col=%7 x=%8 y=%9 ").arg("QL").arg("@getCellAtRC()").arg( textS ).arg("equal").arg("no_notes").arg(row).arg(col).arg(localPos.x()).arg(localPos.y());
            //QString value=get_valueFromWidget_useOptions(cwidget,)

            QString value=cwidget->property(propName.toLocal8Bit().constData()).toString();
            QDRTestMaster::setTextOnWidget(QDRTestMaster::controlPanel,"cValue_label",value);

            return 0;
        }
//------------------------------------------------------------
int QDRTestMaster::rcv_controlPanelAddTest()
        {
            QString checkName=QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,"checkName_lineEdit");
            checkName=checkName.replace(" ","_");
            QString namePath=QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,"cWidget_lineEdit");
            QString propertyName=QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,"property_comboBox");
            QString propertyValue=QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,"checkValue_lineEdit");
            propertyValue = QDRTestMaster::escapeCharacters(propertyValue," ");
            propertyValue = QDRTestMaster::escapeCharacters(propertyValue,"\\");
            QString note=QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,"cNote_lineEdit");
            note=note.replace(" ","_");

            QString compareType=QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,"compareType_comboBox");

            rcv_recordAction(
                      QDateTime::currentDateTime(),
                      namePath,
                      QString("TestValue"),
                      QString("checkid=%1 property=%2 value=%3 compareType=%4 note=%5").arg(checkName).arg(propertyName).arg(propertyValue).arg(compareType).arg(note)
                      );//compareType(s) are: equal more less in notin contain notcontain
                        //пока поддерживается только equal
            return 0;
        }

//------------------------------------------------------------
// ждем виджет или собственно проверяем его наличие.
int QDRTestMaster::rcv_controlPanelAddWait()
        {
          QString namePath=QDRTestMaster::getTextOnWidget(QDRTestMaster::controlPanel,"cWidget_lineEdit");
          rcv_recordAction(
                      QDateTime::currentDateTime(),
                      namePath,
                      QString("WaitWidget"),
                      QString("timeout=2500 ")
                  );//compareType(s) are: equal more less in notin contain notcontain
        }



/*==================================================================

    t_globalEventFilter

*/

QDRTestMaster_eventFilter::QDRTestMaster_eventFilter(QDRTestMaster *parent) :
    QObject(parent)
{
    testMaster=parent;
    filteredWindowName="";
}

//------------------------------------------------------------------
/*


*/
bool QDRTestMaster_eventFilter::eventFilter(QObject *obj, QEvent *event)
{
    QEvent::Type ev_type=event->type();
    QString className=obj->metaObject()->className();
    QString namePath,pref="          ";
    bool justMarkFiltered=__justMarkFilteredEvents;//=false;
    int cGX;
    int cGY;
    bool ok, noMessages=true;
    namePath="";

//    if (ev_type == QEvent::Timer)
//        {
//            QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
//            if (timerEvent->timerId()==qApp_PlayTimerId)
//                testMaster->playNextActionTimerEvent();

//        };


/*TODO:
QEvent::Wheel
QEvent::ContextMenu
QEvent::Clipboard
QEvent::DragEnter
QEvent::DragLeave
QEvent::DragMove
QEvent::Drop

QEvent::MouseTrackingChange????
*/

    if (obj->isWidgetType())
        {
               namePath=QDRTestMaster::get_namePathOfWidget(static_cast<QWidget *>(obj), &ok, noMessages);
               //if (!ok)
               //    return QObject::eventFilter(obj, event);

        }
      else
        {
            return QObject::eventFilter(obj, event);
        };


    if (ev_type == QEvent::KeyPress)
        {
            //if (obj->isWidgetType())
                {
                    QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
                    QWidget *sourceObjLink = static_cast<QWidget *>(obj);
                    {
                        if ((keyEvent->key()==Qt::Key_T) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                          {//контрольная панель!
                            keyEvent->ignore();
                            qDebug() << "Ctrl+ALT+T :: " << namePath;
                            testMaster->rcv_agentPanel_linksActivated("#ControlPanel::toCursorPos");
                            return true;
                          }
                        else if ((keyEvent->key()==Qt::Key_W) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                          {//выбрать виджет! и добавить проверку его визуального свойства
                            keyEvent->ignore();
                            testMaster->rcv_agentPanel_linksActivated("@SelectWidget");
                            return true;
                          }
                        else if ((keyEvent->key()==Qt::Key_E) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                          {//проверка наличия виджета (выбор виджета)
                            keyEvent->ignore();
                            testMaster->rcv_agentPanel_linksActivated("@SelectWidget4WaitAndCheck");
                            return true;
                          }
                        else if ((keyEvent->key()==Qt::Key_D) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                          {//проверка наличия виджета (выбор виджета)
                            keyEvent->ignore();
                            testMaster->rcv_agentPanel_linksActivated("@SelectWidget4AdvancedDefaultValueCheck");
                            return true;
                          }

//                                else if ((keyEvent->key()==Qt::Key_S) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
//                                  {//выбрать виджет и субвиджет с вызовом скрипта для проверки теста
//                                      keyEvent->ignore();
//                                  };

                        else if ((keyEvent->key()==Qt::Key_P) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                          {//остановить действие. запись, проигрывание
                            keyEvent->ignore();
                            testMaster->rcv_agentPanel_linksActivated("@StopAction");
                            return true;
                          };

                    };

                    if (sourceObjLink==QApplication::focusWidget())
                        {
                            //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink, &ok, noMessages);
                            QString keyText=keyEvent->text();
                            if (keyEvent->key()==Qt::Key_Return) keyText="";//.replace("\n","{ENTER}");
                            if (keyEvent->key()==Qt::Key_Enter) keyText="";//.replace("\n","{ENTER}");
                            int key_int = (int)keyEvent->key();
                            if (!keyText.isEmpty()) keyText="\\"+keyText;
                            keyText = QDRTestMaster::escapeCharacters(keyText," ");
                            keyText = QDRTestMaster::escapeCharacters(keyText,"\\");

                            //qDebug() << QString("INFO: {%2}[%3]::QEvent::Key +[%1]\n  (%4)").arg(keyEvent->text()).arg(obj->objectName()).arg(className).arg(namePath);
                           if (!namePath.contains(filteredWindowName))
                            testMaster->rcv_recordAction(
                                        QDateTime::currentDateTime(),
                                        namePath,
                                        QString(pref+"KeyPress"),
                                        QString("key=%1 text=%2 modifiers=%3 isautorepeat=%4").arg(key_int).arg(keyText).arg((int)keyEvent->modifiers()).arg(QDRTestMaster::bool2string(keyEvent->isAutoRepeat()))
                                        );
                        };
                };
        }
    else   if (ev_type == QEvent::KeyRelease)
        {
            //if (obj->isWidgetType())
            {
                QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
                QWidget *sourceObjLink = static_cast<QWidget *>(obj);

                { //комбинации клавиш отпускания - шлем то-же самое но с "(keyReleased)"
                    if ((keyEvent->key()==Qt::Key_T) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                      {//контрольная панель!
                        keyEvent->ignore();
                        //qDebug() << "Ctrl+ALT+T :: " << namePath;
                        testMaster->rcv_agentPanel_linksActivated("#ControlPanel(keyReleased)");
                        return true;
                      }
                    else if ((keyEvent->key()==Qt::Key_W) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                      {//выбрать виджет! и добавить проверку его визуального свойства
                        keyEvent->ignore();
                        testMaster->rcv_agentPanel_linksActivated("@SelectWidget(keyReleased)");
                        return true;
                      }
                    else if ((keyEvent->key()==Qt::Key_E) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                      {//проверка наличия виджета (выбор виджета)
                        keyEvent->ignore();
                        return true;
                      }

//                                else if ((keyEvent->key()==Qt::Key_S) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
//                                  {//выбрать виджет и субвиджет с вызовом скрипта для проверки теста
//                                      keyEvent->ignore();
//                                  };

                    else if ((keyEvent->key()==Qt::Key_P) and (keyEvent->modifiers()==Qt::ControlModifier+Qt::AltModifier) )
                      {//остановить действие. запись, проигрывание
                        keyEvent->ignore();
                        testMaster->rcv_agentPanel_linksActivated("@StopAction(keyReleased)");
                        return true;
                      };

                };
                if (sourceObjLink==QApplication::focusWidget())
                    {
                        //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink);
                        //qDebug() << QString("INFO: {%2}[%3]::QEvent::Key -[%1]\n  (%4)").arg(keyEvent->text()).arg(obj->objectName()).arg(className).arg(namePath);
                        QString keyText=keyEvent->text();
                        if (keyEvent->key()==Qt::Key_Return) keyText="";//.replace("\n","{ENTER}");
                        if (keyEvent->key()==Qt::Key_Enter) keyText="";//.replace("\n","{ENTER}");
                        int key_int = (int)keyEvent->key();
                        if (!keyText.isEmpty()) keyText="\\"+keyText;
                        //keyText = QDRTestMaster::escapeCharacters(keyText," ");
                        keyText = QDRTestMaster::escapeCharacters(keyText,"\\");

                           if (!namePath.contains(filteredWindowName))
                               testMaster->rcv_recordAction(
                                    QDateTime::currentDateTime(),
                                    namePath,
                                    QString(pref+"KeyRelease"),
                                    QString("key=%1 text=%2 modifiers=%3 isautorepeat=%4").arg(key_int ).arg(keyText).arg((int)keyEvent->modifiers()).arg(QDRTestMaster::bool2string(keyEvent->isAutoRepeat()))
                                    );
                    };
            };
            //if (obj->isWidgetType())  namePath=QDRTestMaster::get_namePathOfWidget(static_cast<QWidget *>(obj));
            //qDebug() << QString("INFO: {%2}[%3]::QEvent::Key -[%1]\n  (%4)").arg(keyEvent->text()).arg(obj->objectName()).arg(className).arg(namePath);
        }
    else if (ev_type == QEvent::MouseButtonPress)
        {
            //if (obj->isWidgetType())
                {
                    QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
                    QWidget *sourceObjLink = static_cast<QWidget *>(obj);
                    //if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())==0 )
                    if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())!=0 ) pref="[filtered]";
                    if ( justMarkFiltered or pref.trimmed().isEmpty())
                        { //а вот если есть дели в данной точке - то он им передаст событие и мы его потом тоже получим. по крайней мере так должно быть)
                            //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink);
                            //qDebug() << QString("INFO: {%3}[%4]::QEvent::Mouse +B at[%1;%2]\n  (%5)").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(obj->objectName()).arg(className).arg(namePath);
                            //QWidget *foundObjLink = QDRTestMaster::get_widgetByNamePath(namePath);
                            //if (sourceObjLink==foundObjLink) qDebug() << "good";

                            int cGX=mouseEvent->globalX();
                            int cGY=mouseEvent->globalY();

                           if (!namePath.contains(filteredWindowName))
                            //((QDRTestMaster *)parent())->moveSelectionWidget(mouseEvent->globalX(),mouseEvent->globalY());
                                testMaster->rcv_recordAction(
                                         QDateTime::currentDateTime(),
                                         namePath,
                                         QString(pref+"MouseButtonPress"),
                                         QString("x=%1 y=%2 button=%3 modifiers=%4 glx=%5 gly=%6").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(QDRTestMaster::QtMouseButton2String(mouseEvent->button())).arg((int)(mouseEvent->modifiers())).arg(cGX).arg(cGY)
                                        );
                        };
                };
        }
    else if (ev_type == QEvent::MouseButtonRelease)
        {
            //if (obj->isWidgetType())
                {
                    QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
                    QWidget *sourceObjLink = static_cast<QWidget *>(obj);
                    //if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())==0 )
                    if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())!=0 ) pref="[filtered]";
                    if ( justMarkFiltered or pref.trimmed().isEmpty())                        { //а вот если есть дели в данной точке - то он им передаст событие и мы его потом тоже получим. по крайней мере так должно быть)
                            //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink);
                            ////qDebug() << QString("INFO: {%3}[%4]::QEvent::Mouse -B at[%1;%2]\n  (%5)").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(obj->objectName()).arg(className).arg(namePath);
                            ////QWidget *foundObjLink = QDRTestMaster::get_widgetByNamePath(namePath);
                            ////if (sourceObjLink==foundObjLink) qDebug() << "good";

                           if (!namePath.contains(filteredWindowName))
                             {
                                testMaster->rcv_recordAction(
                                        QDateTime::currentDateTime(),
                                        namePath,
                                        QString(pref+"MouseButtonRelease"),
                                        QString("x=%1 y=%2 button=%3 modifiers=%4 glx=%5 gly=%6").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(QDRTestMaster::QtMouseButton2String(mouseEvent->button())).arg((int)(mouseEvent->modifiers())).arg(cGX).arg(cGY)
                                        );
                            };
//                            else
//                             {//события панели надо обрабатывать отдельно. что бы мы могли реагировать в любом случае.
//                                testMaster->rcv_recordAction(
//                                        QDateTime::currentDateTime(),
//                                        namePath,
//                                        QString(pref+"MouseButtonRelease"),
//                                        QString("x=%1 y=%2 button=%3 modifiers=%4 glx=%5 gly=%6").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(QDRTestMaster::QtMouseButton2String(mouseEvent->button())).arg((int)(mouseEvent->modifiers())).arg(cGX).arg(cGY)
//                                        );

//                             };
                        };
                };
        }
    else if (ev_type == QEvent::MouseButtonDblClick)
        {
            //if (obj->isWidgetType())
                {
                    QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
                    QWidget *sourceObjLink = static_cast<QWidget *>(obj);
                    //if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())==0 )
                    if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())!=0 ) pref="[filtered]";
                    if ( justMarkFiltered or pref.trimmed().isEmpty())                        { //а вот если есть дели в данной точке - то он им передаст событие и мы его потом тоже получим. по крайней мере так должно быть)
                            //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink);
                            ////qDebug() << QString("INFO: {%3}[%4]::QEvent::Mouse -B at[%1;%2]\n  (%5)").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(obj->objectName()).arg(className).arg(namePath);
                            ////QWidget *foundObjLink = QDRTestMaster::get_widgetByNamePath(namePath);
                            ////if (sourceObjLink==foundObjLink) qDebug() << "good";

                           if (!namePath.contains(filteredWindowName))
                                testMaster->rcv_recordAction(
                                        QDateTime::currentDateTime(),
                                        namePath,
                                        QString(pref+"MouseButtonDblClick"),
                                        QString("x=%1 y=%2 button=%3 modifiers=%4 glx=%5 gly=%6").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(QDRTestMaster::QtMouseButton2String(mouseEvent->button())).arg((int)(mouseEvent->modifiers())).arg(cGX).arg(cGY)
                                        );
                        };
                };
        }
    else if (ev_type == QEvent::Move)
        {

            //if (obj->isWidgetType())
            {
                QMoveEvent *moveEvent = static_cast<QMoveEvent *>(event);
                QWidget *sourceObjLink = static_cast<QWidget *>(obj);
                //Тут надо фильтровать только то, что находится под курсором мыши.
                //события дочерним виджетам оно само потом разошлет.
                QPoint curPos=QCursor::pos();
                if (
                    (sourceObjLink->frameGeometry().contains(curPos))//if (sourceObjLink->geometry().contains(curPos))
                   and
                    (sourceObjLink->isActiveWindow())  //полагаем, что таскать можно только активные окна
                   )
                   {

                        //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink);

                        int winMoveX=moveEvent->pos().x()-moveEvent->oldPos().x();
                        int winMoveY=moveEvent->pos().y()-moveEvent->oldPos().y();

                       if (!namePath.contains(filteredWindowName))
                         {
                            testMaster->rcv_recordAction(
                                      QDateTime::currentDateTime(),
                                      namePath,
                                      QString(pref+"Move"),
                                      QString("movex=%1 movey=%2 ").arg(winMoveX).arg(winMoveY)
                                      );
                         }
                       else
                         {

                         };
                   };
            };

        }
    else if (ev_type == QEvent::Resize) //QResizeEvent
        {
            //if (obj->isWidgetType())
                {
                    QResizeEvent *resizeEvent = static_cast<QResizeEvent *>(event);
                    QWidget *sourceObjLink = static_cast<QWidget *>(obj);
                    //Тут надо фильтровать только то, что находится под курсором мыши.
                    //события дочерним виджетам оно само потом разошлет.
                    QPoint curPosGlob=QCursor::pos();
                    QPoint curPos=sourceObjLink->mapFromGlobal(curPosGlob);
                    QRect geometry;
                    geometry.setWidth(sourceObjLink->frameGeometry().width());
                    geometry.setHeight(sourceObjLink->frameGeometry().height());

                    if (
                            (geometry.contains(curPos))  // && (!sourceObjLink->geometry().contains(curPos)) )
                          and
                            (sourceObjLink->isActiveWindow())
                       )
                       {
                            //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink);

                            int height=resizeEvent->size().height();
                            int width=resizeEvent->size().width();

                            if (!namePath.contains(filteredWindowName))
                                testMaster->rcv_recordAction(
                                          QDateTime::currentDateTime(),
                                          namePath,
                                          QString(pref+"Resize"),
                                          QString("height=%1 width=%2 ").arg(height).arg(width)
                                          );
                       };
                };

        }
    else if (ev_type == QEvent::MouseMove)
        {
            //if (obj->isWidgetType())
                {
                    QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
                    QWidget *sourceObjLink = static_cast<QWidget *>(obj);
                    //if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())==0 )
                    if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())!=0 ) pref="[filtered]";
                    if ( justMarkFiltered or pref.trimmed().isEmpty())
                        {

                            ///а вот если есть дели в данной точке - то он им передаст событие и мы его потом тоже получим. по крайней мере так должно быть)
                            //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink);
                            ///qDebug() << QString("INFO: {%3}[%4]::QEvent::MouseMove ->[%1;%2]\n  (%5)").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(obj->objectName()).arg(className).arg(namePath);
                            ///QWidget *foundObjLink = QDRTestMaster::get_widgetByNamePath(namePath);
                            ///if (sourceObjLink==foundObjLink) qDebug() << "good";

                            int cLX=mouseEvent->x();
                            int cLY=mouseEvent->y();
                            int cGX=mouseEvent->globalX();
                            int cGY=mouseEvent->globalY();


//                            int winMoveX=0;
//                            int winMoveY=0;
//                            if (oldWidget==sourceObjLink) //ВНИМАНИЕ! не будет работать когда justMarkFiltered==true///
//                                {
//                                    winMoveX=((cGX-cLX)-oldDeltaGxLx);
//                                    winMoveY=((cGY-cLY)-oldDeltaGyLy);
//                                };

                            if (!namePath.contains(filteredWindowName))
                                {
                                    testMaster->rcv_recordAction(
                                              QDateTime::currentDateTime(),
                                              namePath,
                                              QString(pref+"MouseMove"),
                                              //QString("x=%1 y=%2").arg(mouseEvent->x()).arg(mouseEvent->y())
                                              //  QString("x=%1 y=%2 button=%3 modifiers=%4 movex=%9 movey=%10 gx=%5 gy=%6 dx=%7 dy=%8 ").arg(cLX).arg(cLY).arg(QDRTestMaster::QtMouseButton2String(mouseEvent->button())).arg((int)(mouseEvent->modifiers())).arg(cGX).arg(cGY).arg(cGX-cLX).arg(cGY-cLY).arg(winMoveX).arg(winMoveY)
                                              //  QString("x=%1 y=%2 button=%3 modifiers=%4 movex=%5 movey=%6 ").arg(cLX).arg(cLY).arg(QDRTestMaster::QtMouseButton2String(mouseEvent->button())).arg((int)(mouseEvent->modifiers())).arg(winMoveX).arg(winMoveY)
                                                QString("x=%1 y=%2 button=%3 modifiers=%4 glx=%5 gly=%6").arg(cLX).arg(cLY).arg(QDRTestMaster::QtMouseButton2String(mouseEvent->button())).arg((int)(mouseEvent->modifiers())).arg(cGX).arg(cGY)
                                              );
                                 }
                              else
                                {
                                  //sourceObjLink->setEnabled(true);

                                };

//                            oldDeltaGxLx=cGX-cLX;
//                            oldDeltaGyLy=cGY-cLY;
//                            oldWidget=sourceObjLink;

                        };
                };
    }
//    else if (ev_type == QEvent::Wheel)
//        {
//            if (obj->isWidgetType())
//                {
//                    QMouseEvent *mouseEvent = static_cast<Q *>(event);
//                    QWidget *sourceObjLink = static_cast<QWidget *>(obj);
//                    if ( sourceObjLink->childAt(mouseEvent->x(),mouseEvent->y())==0 )
//                        { //а вот если есть дели в данной точке - то он им передаст событие и мы его потом тоже получим. по крайней мере так должно быть)
//                            //namePath=QDRTestMaster::get_namePathOfWidget(sourceObjLink);
//                            ///qDebug() << QString("INFO: {%3}[%4]::QEvent::MouseMove ->[%1;%2]\n  (%5)").arg(mouseEvent->x()).arg(mouseEvent->y()).arg(obj->objectName()).arg(className).arg(namePath);
//                            ///QWidget *foundObjLink = QDRTestMaster::get_widgetByNamePath(namePath);
//                            ///if (sourceObjLink==foundObjLink) qDebug() << "good";

//                            ((QDRTestMaster*)parent())->rcv_userAction(
//                                        QDateTime::currentDateTime(),
//                                        namePath,
//                                        QString(pref+"Wheel"),
//                                        QString("x=%1 y=%2").arg(mouseEvent->x()).arg(mouseEvent->y())
//                                        );
//                        };
//                };
//    }
    //else
        {
            // standard event processing
            //qDebug() << "EventType "<< event->type();
            return QObject::eventFilter(obj, event);
        };
}
